# PYMT Plugin integration
IS_PYMT_PLUGIN = True
PLUGIN_TITLE = 'Napier Browser'
PLUGIN_AUTHOR = 'Jay Bradley'
PLUGIN_DESCRIPTION = 'Browse through file and search web resources'


from pymt import *
import os
import random
from OpenGL.GL import *
from pdfbook import *
import MTYouTube
import MTPicasa
import utilities
import platform
import MTCircularMenu
import ENICEMenu.ENICEMenu

current_dir = os.path.dirname(__file__)

#local_media_places = {"USB": ["./resources/USB/", "resources/graphics/usb.png"], "DropBox": ["./resources/DropBox/", "resources/graphics/dropbox.png"], "Napier S Drive": ["./resources/Napier S Drive/", "resources/graphics/sdrive.png"]} # for development
local_media_places = {"USB": ["./resources/USB/", "resources/graphics/usb.png"], "DropBox": ["C:\Users\Owner\Documents\My Dropbox", "resources/graphics/dropbox.png"], "Napier S Drive": ["./resources/Napier S Drive/", "resources/graphics/s.png"], "Computer": ["C://", "resources/graphics/c.png"]} # for the table

#remote_media_places = {"YouTube": ["http://youtube", "resources/graphics/youtube.png"], "Picasa": ["http://picasa", "resources/graphics/picassa.png"]} # for development
remote_media_places = {"YouTube": ["http://youtube", "resources/graphics/youtube.png"], "Picasa": ["http://picasa", "resources/graphics/picassa.png"]} # for the table

number_of_remote_items_loaded = 5

image_file_extensions = ["jpg", "png"] # lowercase no preceeding dot
video_file_extensions = ["avi", "mpg", "flv", "mov", "mp4"] # lowercase no preceeding dot
document_file_extensions = ["pdf"]


file_extensions = []
file_extensions.extend(image_file_extensions)
file_extensions.extend(video_file_extensions)
file_extensions.extend(document_file_extensions)


local_and_removeable_media_places = local_media_places # this dictionary is reallocated each time a browser is opened to check if any removeable drives have been added

acceptable_files_regular_expression = "^.+\.("
for extension in file_extensions:
    acceptable_files_regular_expression += "(" + extension + ")|"
for extension in file_extensions:
    acceptable_files_regular_expression += "(" + extension.upper() + ")|"
acceptable_files_regular_expression = acceptable_files_regular_expression[:-1] + ")$"

class MTNapierBrowser(MTWidget):
    def __init__(self, **kwargs):
        super(MTNapierBrowser, self).__init__(**kwargs)
        #MTWidget.__init__(self, **kwargs)

        # store a link to the holding inner window if there is one, otherwise it's none
        kwargs.setdefault('holding_inner_window', None)
        self.holding_inner_window = kwargs.get("holding_inner_window")

        # main vertical layout for the media buttons and space above
        self.main_layout = MTBoxLayout(orientation='vertical', size = self.size, invert=True)#, bg_color=(0,0,1,0.3)) # this must have the size set here
        #self.main_layout = MTBoxLayout(orientation='vertical', size_hint=(1.0,1.0), bg_color=(0,0,1,0.3)) This does not work for instance
        self.add_widget(self.main_layout)
        
        # add buttons for each possible media location
        self.media_buttons_max_height = 50
        # size hint = 0.3 means that this should be a third of the size of other stuff in the parent layout
        #self.media_button_layout = MTBoxLayout(orientation='horizontal', spacing = 10, size_hint=(1.0, None), size=(self.width, self.media_buttons_max_height))#, size_hint=(1.0, 0.3))#, bg_color=(1,0,0,0.5))
        self.media_button_layout = MTBoxLayout(orientation='horizontal', size_hint=(1.0, None), size=(self.width, self.media_buttons_max_height))#, size_hint=(1.0, 0.3))#, bg_color=(1,0,0,0.5))
        self.main_layout.add_widget(self.media_button_layout)

        # check and add extra drive to local_media_places
        # add mapped drives for windows (could do for other OS's too)
        extra_drives = {}
        if(platform.system() == "Linux"):
            print "on linux not adding any extra drives"
        elif(platform.system() == "Windows"):
            extra_drives = utilities.find_windows_drives()
            print "Adding extra drives:", extra_drives

        local_and_removeable_media_places = local_media_places
        for drive in extra_drives:
            local_and_removeable_media_places[drive] = [drive + ":\\", "isARemovableDrive-" + drive]

        self.media_buttons = {}
        for media_placename in local_and_removeable_media_places.keys():
            if(local_and_removeable_media_places[media_placename][1].startswith("isARemovableDrive-")):
                #self.media_buttons[media_placename] = MTButton(label=media_placename, size_hint=(1.0, 1.0))
                self.media_buttons[media_placename] = MTImageButton(filename="resources/graphics/usb.png", label=media_placename, size_hint=(1.0, 1.0))
            else:
                #self.media_buttons[media_placename] = MTButton(label=media_placename, size_hint=(1.0, 1.0))
                #self.media_buttons[media_placename] = MTImageButton(filename=local_and_removeable_media_places[media_placename][1], label=media_placename, scale=1, size_hint=(1.0, 1.0))
                self.media_buttons[media_placename] = MTImageButton(filename=local_and_removeable_media_places[media_placename][1], label=media_placename, size_hint=(1.0, 1.0))
            self.media_buttons[media_placename].connect('on_press', self.media_button_on_press)
            self.media_button_layout.add_widget(self.media_buttons[media_placename])
             
        for media_placename in remote_media_places.keys():
            #self.media_buttons[media_placename] = MTButton(label=media_placename, size_hint=(1.0, 1.0))
            #self.media_buttons[media_placename] = MTImageButton(filename=remote_media_places[media_placename][1], label=media_placename, scale=1, size_hint=(1.0, 1.0))
            self.media_buttons[media_placename] = MTImageButton(filename=remote_media_places[media_placename][1], label=media_placename, size_hint=(1.0, 1.0))
            self.media_buttons[media_placename].connect('on_press', self.media_button_on_press)
            self.media_button_layout.add_widget(self.media_buttons[media_placename])
        
        self.file_browser_layout = None
        self.remote_media_search_form_layout = None
        self.media_viewer = None
        self.add_media_viewer([])
        
        @self.event
        def on_parent_resize(width, height):
            #print "MTNapierBrowser on_parent_resize"
            self.resize_browser(width, height)
            
    def resize_browser(self, new_width, new_height):
        #print "resize_browser " + str(new_width) + ", " + str(new_height)
        self.main_layout.size = (new_width, new_height)


    def media_button_on_press(self, *largs):
        # Check local media
        for media_placename in local_and_removeable_media_places.keys():
            if(self.media_buttons[media_placename].state == "down"):
                print self.media_buttons[media_placename].label + " down. Directory: " + local_and_removeable_media_places[self.media_buttons[media_placename].label][0]
                self.add_file_browser(local_and_removeable_media_places[self.media_buttons[media_placename].label][0])
        # check remote media
        for media_placename in remote_media_places.keys():
            if(self.media_buttons[media_placename].state == "down"):
                print self.media_buttons[media_placename].label + " down. URI: " + remote_media_places[self.media_buttons[media_placename].label][0]
                self.add_remote_media_search_form(remote_media_places[self.media_buttons[media_placename].label][0])
    
    def remove_file_browser(self):
        if(self.file_browser_layout in self.main_layout.children):
            self.main_layout.remove_widget(self.file_browser_layout)
            self.file_browser_layout = None
    
    def remove_remote_media_search_form(self):
        if(self.remote_media_search_form_layout in self.main_layout.children):
            self.main_layout.remove_widget(self.remote_media_search_form_layout)
            self.remote_media_search_form_layout = None
    
    def hide_media_viewer(self):
        self.main_layout.remove_widget(self.media_viewer)
        
    def add_remote_media_search_form(self, uri):
        # add search form widget
        
        self.remove_file_browser() # remove it if it's there
        
        # if the search form isn't already showing
        if(self.remote_media_search_form_layout is None):
        
            # if there's a media viewer then hide it
            if(self.media_viewer != None):
                self.hide_media_viewer()
                
            # add the file browser layout
            self.remote_media_search_form_layout = MTBoxLayout(orientation='vertical', size_hint=(1.0,1.0), invert=True)
            self.main_layout.add_widget(self.remote_media_search_form_layout)
            
            # add the button layout
            self.remote_media_search_form_button_layout = MTBoxLayout(orientation='horizontal', size_hint=(1.0, 1.0))
            self.remote_media_search_form_layout.add_widget(self.remote_media_search_form_button_layout)
            
            # add select and cancel buttons
            self.remote_media_search_form_search_button = MTButton(label="Search", size_hint=(1.0, 1.0))
            @self.remote_media_search_form_search_button.event
            def on_press(*largs):
                if(len(self.remote_media_search_form.value) > 0):
                    print 'Search on remote media search form.'
                    print "Search " + uri + " for " + self.remote_media_search_form.value
                    self.search_remote_media(uri, [self.remote_media_search_form.value]) # just one search term at the moment
                self.remote_media_search_form.hide_keyboard()
                self.remove_remote_media_search_form()
                self.show_media_viewer()
            
            self.remote_media_search_form_cancel_button = MTButton(label="Cancel", size_hint=(0.5, 1.0))
            @self.remote_media_search_form_cancel_button.event
            def on_press(*largs):
	            print 'Cancel on remote media search form'
	            self.remote_media_search_form.hide_keyboard()
	            self.remove_remote_media_search_form()
	            self.add_media_viewer([])
	            
            self.remote_media_search_form_button_layout.add_widget(self.remote_media_search_form_search_button)
            self.remote_media_search_form_button_layout.add_widget(self.remote_media_search_form_cancel_button)

            # add the media search form itself
            self.remote_media_search_form = MTTextInput(size_hint=(1.0, 1.0), keyboard_to_root=True, place_keyboard_by_control=True, get_initial_keyboard_rotation_from = self.parent.parent)
            self.remote_media_search_form_layout.add_widget(self.remote_media_search_form)
        else:
            # set new URI somehow
            pass
    

    def search_remote_media(self, uri, search_terms):
        if(uri == 'http://youtube'): # if YouTube
            print "YouTube search_term is " + str(search_terms)         
            self.youtube_search = MTYouTube.YoutubeSearch(self, search_terms, number_of_remote_items_loaded)
            self.youtube_search.start()
        elif(uri == 'http://picasa'): # if Picasa
            print "Picasa search_term is " + str(search_terms)         
            MTPicasa.PicasaSearch(self, search_terms, number_of_remote_items_loaded)
    
    def add_remote_video(self, uri):
        #print "add_remote_video with URI ", uri
        
        #if(self.done_once == None): 
        self.currently_viewing_files[uri] = MTYouTube.MTYouTubeVideoWidget(uri=uri)
        self.media_viewer_clip_region.add_widget(self.currently_viewing_files[uri])

        # set the initial position, rotation and scale to sensible random settings            
        self.currently_viewing_files[uri].pos = self.get_random_initial_position()
        self.currently_viewing_files[uri].rotation = self.get_random_initial_rotation()
        #self.currently_viewing_files[uri].scale = self.get_random_initial_scale(self.currently_viewing_files[uri])
        #    self.done_once = True
            
    
    def add_file_browser(self, start_path):
        # add file browser widget
        self.remove_remote_media_search_form() # remove it if it's showing
        # if the file browser isn't already showing
        #print self.file_browser_layout
        if(self.file_browser_layout is None):
        
            # if there's a media viewer then hide it
            if(self.media_viewer != None):
                self.hide_media_viewer()
                
            # add the file browser layout
            self.file_browser_layout = MTBoxLayout(orientation='vertical', invert=True, size_hint=(1.0, 1.0))
            self.main_layout.add_widget(self.file_browser_layout)
            
            # add the button layout
            self.file_browser_button_layout = MTBoxLayout(orientation='horizontal', size_hint=(1.0, 0.2))
            self.file_browser_layout.add_widget(self.file_browser_button_layout)
            
            # add select and cancel buttons
            self.file_browser_select_button = MTButton(label="Select", size_hint=(1.0, 1.0))
            @self.file_browser_select_button.event
            def on_press(*largs):
	            print 'Select on file browser. Files: ' + str(self.file_browser.selection)
	            self.remove_file_browser()
	            self.add_media_viewer(self.file_browser.selection)
            
            self.file_browser_cancel_button = MTButton(label="Cancel", size_hint=(0.5, 1.0))
            @self.file_browser_cancel_button.event
            def on_press(*largs):
	            print 'Cancel on file browser'
	            self.remove_file_browser()
	            self.add_media_viewer([])
	            
            self.file_browser_button_layout.add_widget(self.file_browser_select_button)
            self.file_browser_button_layout.add_widget(self.file_browser_cancel_button)

            # add the file browser view itself
            self.file_browser = MTFileBrowserView(do_x=True, path=start_path, size_hint=(1,1), filters=[acceptable_files_regular_expression], multipleselection=True, view=MTFileIconEntryView, invert_order=False, cls="file_browser_view")
            self.file_browser_layout.add_widget(self.file_browser)
            self.file_browser.update() # must be called to see anything
        else:
            self.file_browser.path = start_path

    def show_media_viewer(self):
        # add the file browser layout if it doesn't already exist
        if(self.media_viewer == None):
            self.media_viewer = MTWidget(size_hint=(1.0,1.0), cls='media_viewer')
            self.media_viewer_clip_region = MTStencilContainer(size_hint=(1.0,1.0), cls='media_viewer_clip_region')
            self.media_viewer.add_widget(self.media_viewer_clip_region)
            
            #@self.media_viewer.event
            @self.media_viewer_clip_region.event
            def on_draw():
                for media in self.media_viewer_clip_region.children:
                #for media in self.media_viewer.children:
                    #print "image pos is", media.pos # pos is the bottom left of the bounding box. So are x and y.
                    #print "bbox", media.bbox
#                    if(media.x < self.media_viewer_clip_region.pos[0]):
#                        media.x = self.media_viewer_clip_region.pos[0]
#                    elif(media.x + media.bbox[1][0] > self.media_viewer_clip_region.width):
#                        media.x = self.media_viewer_clip_region.width - media.bbox[1][0]
#                    if(media.y < self.media_viewer_clip_region.pos[1]):
#                        media.y = self.media_viewer_clip_region.pos[1]
#                    elif(media.y + media.bbox[1][1] > self.media_viewer_clip_region.pos[1] + self.media_viewer_clip_region.height):
#                        media.y = self.media_viewer_clip_region.pos[1] + self.media_viewer_clip_region.height - media.bbox[1][1]
                    percentage_outlying = 0.8 # keep ten percent of an item viewable in the window
                    viewable_width = media.bbox[1][0] * percentage_outlying
                    viewable_height = media.bbox[1][1] * percentage_outlying
                    if(media.x + viewable_width < self.media_viewer_clip_region.pos[0]):
                        media.x = self.media_viewer_clip_region.pos[0] - viewable_width
                    elif(media.x + media.bbox[1][0] - viewable_width > self.media_viewer_clip_region.width):
                        media.x = self.media_viewer_clip_region.width - media.bbox[1][0] + viewable_width
                    if(media.y + viewable_height < self.media_viewer_clip_region.pos[1]):
                        media.y = self.media_viewer_clip_region.pos[1] - viewable_height
                    elif(media.y + media.bbox[1][1] - viewable_height > self.media_viewer_clip_region.pos[1] + self.media_viewer_clip_region.height):
                        media.y = self.media_viewer_clip_region.pos[1] + self.media_viewer_clip_region.height - media.bbox[1][1] + viewable_height
            self.currently_viewing_files = {}

        if(self.media_viewer not in self.main_layout.children):
            self.main_layout.add_widget(self.media_viewer)

    def on_touch_move(self, touch):
        #print "MTNapierBrowser::on_touch_move"
        #print "touch.xmot", touch.xmot, "touch.ymot", touch.ymot, "touch.is_held", touch.is_held, "touch class", touch.__class__.__name__
        if(touch.is_held and (touch.xmot == 0 and touch.ymot == 0)): # touch held event is detected by a touch move event with no movement set in xmot or ymot
            #print "A held touch dx =", touch.xmot, touch.sx, touch.oxpos, touch.dxpos, touch.distance
            start_pos = self.to_window(touch.x, touch.y, True)
            #self.circular_menu = MTCircularMenu.MTCircularMenu(pos=start_pos)#, start_angle = 150, end_angle = 210 )#, sub_buttons_radius_extra_spacing = 50)
            self.circular_menu = ENICEMenu.ENICEMenu.ENICEMenu(pos=start_pos)#, start_angle = 150, end_angle = 210 )#, sub_buttons_radius_extra_spacing = 50)
            # check that the fullscreen method is there to be called
            #print "self.parent.parent", self.parent.parent.__class__.__name__
            #print "self.parent.parent.is_fullscreen", self.parent.parent.is_fullscreen
            #func = getattr(self.parent.parent, "fullscreen", None)
            #if callable(func):
            if self.parent.parent.is_fullscreen == False:
                self.circular_menu.add_sub_button("resources/graphics/fullscreen.png", callback_function=self.holding_inner_window.fullscreen)
            else:
                self.circular_menu.add_sub_button("resources/graphics/unfullscreen.png", callback_function=self.holding_inner_window.unfullscreen)
            self.circular_menu.add_sub_button("resources/graphics/close.png", callback_function=self.holding_inner_window.close)
            self.circular_menu.add_sub_button("resources/graphics/grid.png", callback_function=self.test_function)
            #self.circular_menu.add_sub_button("resources/graphics/close.png", self.test)
            #self.circular_menu.add_sub_button("resources/graphics/close.png", self.test)
            
            getWindow().add_widget(self.circular_menu)
            self.circular_menu.show_sub_buttons()
                    
    def test_function(self, touch):
        print "test function"

    def add_media_viewer(self, filenames):
        self.show_media_viewer()
        #print "Add media viewer for files " + str(filenames)
        
        for filename in filenames:
        
            # if it's a directory then call this function again with all the files and directories in it
            if(filename.endswith("../")):
                pass
            elif(os.path.isdir(filename)):
                print filename, "is a directory"
                files_in_subdirectory = []
                for subfile in os.listdir(filename):
                    files_in_subdirectory.append(os.path.join(filename, subfile))
                    
                self.add_media_viewer(files_in_subdirectory)
            else:
                print "Adding file to media viewer: " + filename
                basename, extension = os.path.splitext(filename) # get the extension - need to remove the dot in the next line
                
                # it's an image
                if(extension.lower()[1:] in image_file_extensions):
                    self.add_image(filename)
                
                # if it's a video
                elif(extension.lower()[1:] in video_file_extensions):
                    self.currently_viewing_files[filename] = MTScatterWidget()
                    video = MTVideo(filename=filename, bordersize=3)
                    self.currently_viewing_files[filename].add_widget(video)
                    connect(video, 'on_resize', self.currently_viewing_files[filename], 'size')
                    self.media_viewer_clip_region.add_widget(self.currently_viewing_files[filename])
                
                # if it's a pdf or other document like that
                elif(extension.lower()[1:] in document_file_extensions):
                    if(extension.lower()[1:] == "pdf"): # if it's a pdf
                        self.currently_viewing_files[filename] = book = MTBook(pdf_filename=filename)
                        self.media_viewer_clip_region.add_widget(self.currently_viewing_files[filename])
                
                else:
                    return # if the filetype is not recognised by its extension then don't add it
                # no matter what type of widget set the initial position, rotation and scale to sensible random settings            
                self.currently_viewing_files[filename].pos = self.get_random_initial_position()
                self.currently_viewing_files[filename].rotation = self.get_random_initial_rotation()
                self.currently_viewing_files[filename].scale = self.get_random_initial_scale(self.currently_viewing_files[filename])

    def add_image(self, filename):
        self.currently_viewing_files[filename] = MTScatterImage(filename=filename, scale=0.1)
        self.media_viewer_clip_region.add_widget(self.currently_viewing_files[filename])
 
    def add_remote_image(self, uri):
        # load image
        image = Loader.image(uri)
        self.currently_viewing_files[uri] = MTScatterImage(image=image, scale=0.1)
        self.media_viewer_clip_region.add_widget(self.currently_viewing_files[uri])
    
    
    def get_random_initial_position(self):
        return Vector(random.randint(0, int(self.media_viewer.width * 0.8)), random.randint(0, int(self.media_viewer.height * 0.8)))
    
    def get_random_initial_rotation(self):
        return random.randint(-30, 30)
    
    def get_random_initial_scale(self, widget): # video is always 100 by 100 for some reason
        # set new widget to be a sensible size given the current size of the browser
        max_size = 0.3
        min_size = 0.4
        #print "new widget size is " + str(widget.size)
        if(widget.size[0] > widget.size[1]): # landscape
            scale_to_browser = float(self.media_viewer.size[0]) / float(widget.size[0]) # scaled to the size of the browser
        else: # portrait
            scale_to_browser = float(self.media_viewer.size[1]) / float(widget.size[1]) # scaled to the size of the browser
        initial_scale = scale_to_browser * random.uniform(min_size, max_size)
        #print "initial_scale is " + str(initial_scale)
        return initial_scale
    
    
    def on_draw(self):
        # TODO these should be in some sort of on_update or something like that. They're needed because the stencil container is added before the media viewer widget is added to anything.
        self.media_viewer_clip_region.size = self.media_viewer.size # need this line to make the clip reion the correct size
        self.media_viewer_clip_region.pos = self.media_viewer.pos # need this line to make the clip reion be in the correct position
        
        #print "self.media_viewer.size is " + str(self.media_viewer.size) + ", self.media_viewer_clip_region.size is " + str(self.media_viewer_clip_region.size)
        #print "self.media_viewer.pos is " + str(self.media_viewer.pos) + ", self.media_viewer_clip_region.pos is " + str(self.media_viewer_clip_region.pos)
        super(MTNapierBrowser, self).on_draw()


